/**
 * spark_src
 */
package com.kingray.openfire.plugin.handler.iq;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.IQRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.disco.ServerFeaturesProvider;
import org.jivesoftware.openfire.handler.IQHandler;
import org.jivesoftware.openfire.session.ClientSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;

import com.kingray.openfire.plugin.dao.EmotionDAO;
import com.kingray.openfire.plugin.dao.impl.EmotionDAOImpl;
import com.kingray.openfire.plugin.packet.IQElementMapping;
import com.kingray.openfire.plugin.packet.KingrayNameSpace;
import com.kingray.openfire.plugin.packet.EmotionIQ.EmotionActionType;
import com.kingray.openfire.plugin.vo.Emotion;
import com.xiongyingqi.convert.XmlConvert;
import com.xiongyingqi.util.Base64;
import com.xiongyingqi.util.DomainHelper;
import com.xiongyingqi.util.EntityHelper;
import com.xiongyingqi.util.FileHelper;
import com.xiongyingqi.util.StringHelper;
/**
 * 处理客户端的表情对象请求
 * @author 瑛琪 <a href="http://xiongyingqi.com">xiongyingqi.com</a>
 * @version 2013-9-5 上午11:11:57
 */
public class EmotionIQHandler extends IQHandler implements ServerFeaturesProvider {
	public static final Logger log = LoggerFactory
			.getLogger(EmotionIQHandler.class);
	public static final KingrayNameSpace QUERY_EMOTION = KingrayNameSpace.QUERY_EMOTION;
	private IQHandlerInfo info;
	private String serverString;
	
	private EmotionDAO emotionDAO;
	private XmlConvert convert;
	/**
	 * @param moduleName
	 */
	public EmotionIQHandler() {
		super("Emotion Handler");	
		emotionDAO = new EmotionDAOImpl();
		convert = new XmlConvert(IQElementMapping.class);
		
		XMPPServer server = XMPPServer.getInstance();
		serverString = server.getServerInfo().getXMPPDomain();
		
		info = new IQHandlerInfo(QUERY_EMOTION.getKey(), QUERY_EMOTION.getValue());
		
		// 注册IQ处理服务
		IQRouter iqRouter = server.getIQRouter();
		iqRouter.addHandler(this);
	}

	/**
	 * <br>2013-9-5 下午2:41:30
	 * @see org.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ)
	 */
	@Override
	public IQ handleIQ(IQ packet) throws UnauthorizedException {
		IQ response = handleEmotionIQ(packet);
		response.setType(IQ.Type.result);
		response.setFrom(serverString);
		JID fromJid = packet.getFrom();
		ClientSession session = XMPPServer.getInstance().getSessionManager().getSession(fromJid);
		if(session == null){ // 
			response.setChildElement(packet.getChildElement().createCopy());
			response.setError(PacketError.Condition.not_authorized);
		}
		return response;
	}
	
	/**
	 * 处理客户端的表情请求包<br>
	 * 客户端与服务端的交流分为以下几种情况：<br>
	 * <b>1、客户端发送添加表情的请求，服务器处理完表情后，则通知其他所有在线的客户端更新表情文件</b><br>
	 * <b>2、客户端登录时，首先获取本地已经存储的表情，然后将这些Id向服务器发送，然后服务器根据客户端传输的已经存在的表情包进行比对，然后传输回给客户端</b><br>
	 * 另外，客户端与服务端表情文件的传输，均使用经过Base64算法编码后的字符串传输<br>
	 * <br>2013-9-5 下午3:42:11
	 * @param packet
	 * @return
	 */
	public IQ handleEmotionIQ(IQ packet){
		IQ response = IQ.createResultIQ(packet);
		
		// 读取根节点数据
		Element element = packet.getChildElement();
		String actionType = element.attributeValue("actionType");// 获取查询方法
		
		List<Element> emotionElements = element.elements();
		Collection<Emotion> emotions = new ArrayList<Emotion>();
		for (Iterator iterator = emotionElements.iterator(); iterator.hasNext();) {
			Element emotionElement = (Element) iterator.next();
			
			Emotion emotion = new Emotion();
			String id = emotionElement.attributeValue("id");
			String emotionString = emotionElement.attributeValue("emotionString");
			String emotionId = emotionElement.attributeValue("emotionId");
			String base64Data = emotionElement.attributeValue("base64Data");
			if(StringHelper.notNullAndNotEmpty(base64Data)){
				File emotionFile = readEmotionFile(base64Data);
				emotion.setEmotionFile(emotionFile);
			}
			if(StringHelper.notNullAndNotEmpty(emotionString)){
				emotion.setEmotionString(emotionString);
			}
			if(StringHelper.notNullAndNotEmpty(emotionId)){
				emotion.setEmotionId(emotionId);
			}
			if(StringHelper.notNullAndNotEmpty(id)){
				try {
					emotion.setId(Integer.parseInt(id));
				} catch (Exception e) {
				}
			}
			emotions.add(emotion);
		}
		
		Element elementResult = null;
		if(actionType.equals(EmotionActionType.ADD_EMOTION.toString())){
			elementResult = handleAddEmotionAction(emotions, packet);
			elementResult.addAttribute("result", "ok");
		} else if(actionType.equals(EmotionActionType.QUERY_COUNT.toString())){
			elementResult = handleQueryEmotionCountAction(emotions, packet);
		} else if(actionType.equals(EmotionActionType.QUERY_SUMMARY.toString())){
			elementResult = handleQueryEmotionSummaryAction(emotions, packet);
		} else if(actionType.equals(EmotionActionType.QUERY_DETAIL.toString())){
			elementResult = handleQueryEmotionDetailAction(emotions, packet);
		}
		
		
		if(elementResult != null){// 将结果节点拼接到根节点
			elementResult.addNamespace("", QUERY_EMOTION.getValue()); // 加入命名空间
			elementResult.addAttribute("actionType", actionType); // 加入actionType
			response.setChildElement(elementResult);
		} else {
			response.setChildElement(packet.getChildElement().createCopy());
			response.setError(PacketError.Condition.not_acceptable);
		}
		return response;
	}
	
	/**
	 * 
	 * <br>2013-9-10 下午9:04:17
	 * @param emotions
	 * @param packet
	 * @return
	 */
	private Element handleQueryEmotionSummaryAction(Collection<Emotion> emotions, IQ packet) {
		Collection<Emotion> emotionsSummary = emotionDAO.getSummaryEmotions();
		Element element = convert.convertVOs(emotionsSummary);
		return element;
	}

	/**
	 * 处理客户端获取表情数量的请求IQ
	 * <br>2013-9-10 下午9:04:14
	 * @param emotions
	 * @param packet
	 * @return
	 */
	private Element handleQueryEmotionCountAction(Collection<Emotion> emotions, IQ packet) {
		Element element = DocumentHelper.createElement(QUERY_EMOTION.getKey());
		int size = emotionDAO.getEmotionSize();
		element.addAttribute("emotionCount", size + "");
		return element;
	}

	
	/**
	 * 处理客户端查询表情服务
	 * <br>2013-9-6 上午10:15:34
	 * @param emotions
	 * @return
	 */
	private Element handleQueryEmotionDetailAction(Collection<Emotion> emotions, IQ packet){
		Element element = DocumentHelper.createElement(QUERY_EMOTION.getKey());
		
		if(emotions.size() > 0){
			Collection<Emotion> serverEmotions = emotionDAO.getEmotionsByIds(emotions);
			element = convert.convertVOs(serverEmotions);
		}
		
		return element;
	}
	
	/**
	 * 处理客户端添加表情的请求
	 * <br>2013-9-6 上午10:15:55
	 * @param emotions
	 * @param packet 
	 * @return
	 */
	private Element handleAddEmotionAction(Collection<Emotion> emotions, IQ packet){
		Element element = DocumentHelper.createElement(QUERY_EMOTION.getKey());
		element.addNamespace("", QUERY_EMOTION.getValue());
		
		Collection<Emotion> emotionsToAdd = new ArrayList<Emotion>();
		for (Iterator iterator = emotions.iterator(); iterator.hasNext();) {
			Emotion emotion = (Emotion) iterator.next();
			Emotion newEmotion = emotionDAO.addEmotion(emotion);
			log.info(EntityHelper.reflectToString(newEmotion));
			emotionsToAdd.add(newEmotion);
		}
		element = convert.convertVOs(emotionsToAdd);
		broadCastEmotions(element, packet);// 将新表情广播
		return element;
	}
	
	
	
	/**
	 * 广播表情
	 * <br>2013-9-5 下午5:12:19
	 * @param element
	 * @param packet 
	 */
	private void broadCastEmotions(final Element element, final IQ packet){
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					IQ iq  = new IQ();
					iq.setChildElement(element);
					iq.setFrom(serverString);
					Collection<ClientSession> sessions = sessionManager.getSessions();
					for (Iterator iterator = sessions.iterator(); iterator.hasNext();) {
						ClientSession clientSession = (ClientSession) iterator.next();
						if(DomainHelper.removeDomain(clientSession.getUsername()).equals(DomainHelper.removeDomain(packet.getFrom().toBareJID()))){
							continue;
						}
						iq.setID(StringHelper.UUID());
						iq.setTo(clientSession.getAddress());
						clientSession.process(iq);
					}
				} catch (Exception e) {
				}
			}
		});
		thread.start();
	}
	
	private static File readEmotionFile(String base64Data){
		File file = null;
		if(base64Data != null && !"".equals(base64Data.trim())){
			byte[] data = Base64.decode(base64Data);
			try {
				file = FileHelper.readBytesToFile(data, FileHelper.validateFile(new File("images/emotions/" + StringHelper.UUID())));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return file;
	}
	

	/**
	 * <br>2013-9-5 下午2:41:30
	 * @see org.jivesoftware.openfire.handler.IQHandler#getInfo()
	 */
	@Override
	public IQHandlerInfo getInfo() {
		return info;
	}
	
	public static void main(String[] args) {
//		try {
//			System.out.println(readEmotionFile(Base64.encodeBytes(FileHelper.readFileToBytes(new File("C:/Users/瑛琪/Desktop/a.gif")))));
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		Emotion emotion = new Emotion();
//		emotion.setEmotionString("aaa");
//		emotion.setEmotionId("111");
//		
//		Collection<Emotion> emotions = new ArrayList<Emotion>();
//		emotions.add(emotion);
//		
//		Emotion emotion2 = new Emotion();
//		emotion2.setEmotionId("111");
//		
//		System.out.println(emotions.contains(emotion2));
		System.out.println("ADD_EMOTION".equals(EmotionActionType.ADD_EMOTION.toString()));
	}

	/**
	 * <br>2013-9-9 下午4:48:54
	 * @see org.jivesoftware.openfire.disco.ServerFeaturesProvider#getFeatures()
	 */
	@Override
	public Iterator<String> getFeatures() {
		return null;
	}


}
